﻿using SqlSugar;
using System.Data;

namespace MassTransitTest.SqlSugarCore
{
    /// <summary>
    /// 数据库操作方法接口
    /// </summary>
    public interface IDbHelper : IDisposable
    {
        /// <summary>
        /// linq操作对象
        /// </summary>
        SqlSugarClient Client { get; }

        /// <summary>
        /// 执行sql
        /// 参考示例：context.Excute("update info_city set memo2=@memo where cityid=@cityid", new { cityid = "00000041", memo = "transtest" });
        /// </summary>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="param">参数对象</param>
        /// <param name="commandType">执行类型，默认为执行sql</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>返回的是操作影响的行数</returns>
        int Excute(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null);

        /// <summary>
        /// 多次执行同一个sql，按照paramList的参数依次执行
        /// 示例：
        ///  var list = new List<City>();
        ///  for (var i = 0; i< 500; i++)
        ///   {
        ///      list.Add(new City { cityid = i.ToString(), citycd = i.ToString(), cityname = $"江山{i}" });
        ///   }
        ///   context.Excute("insert into info_city(cityid,citycd,cityname)values(@cityid,@citycd,@cityname)", list);
        /// </summary>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="paramList">参数对象集合</param>
        /// <param name="commandType">执行类型，默认为执行sql</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>返回的是操作影响的行数</returns>
        int Excute(string sql, IEnumerable<object> paramList, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null);

        /// <summary>
        /// 执行sql并返回查询的第一行第一列数据
        /// 示例：context.ExecuteScalar<int>("select count(1) from info_city");
        /// </summary>
        /// <typeparam name="TV">返回的数据类型</typeparam>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="param">参数对象</param>
        /// <param name="commandType"></param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>返回第一行第一列数据</returns>
        TV ExecuteScalar<TV>(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null);

        /// <summary>
        /// 返回多条数据对象
        ///  select查询的使用
        ///  示例：context.QueryMultiple<City>("select * from info_city where cityid=@cityid", new { cityid = "00000041" });
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="param">参数对象</param>
        /// <param name="commandType">执行类型，默认为执行sql</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>查询的数据集合</returns>
        IEnumerable<T> QueryMultiple<T>(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null) where T : class;

        /// <summary>
        /// 返回第一条数据结果，没有则返回default(T)
        /// select查询的使用
        /// 示例：context.QueryFirstOrDefault<City>("select top 1 * from info_city");
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="param">参数对象</param>
        /// <param name="commandType">执行类型，默认为执行sql</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>返回sql执行的第一条数据结果，没有则返回default(T)</returns>
        T QueryFirstOrDefault<T>(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null) where T : class;

        /// <summary>
        /// 执行sql，返回DataTable
        /// 示例：context.Query("select * from info_city where cityid=@cityid", new { cityid = "00000041" });
        /// </summary>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="param">参数对象</param>
        /// <param name="commandType">执行类型，默认为执行sql</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>查询结果的DataTable对象</returns>
        DataTable Query(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null);

        /// <summary>
        /// 执行sql，返回DataTable
        /// 含主键信息，性能比 Query要慢很多，非必须不要使用
        /// 示例：context.QueryWitkKeyInfo("select * from info_city where cityid=@cityid", new { cityid = "00000041" });
        /// </summary>
        /// <param name="sql">需要执行的sql</param>
        /// <param name="param">参数对象</param>
        /// <param name="commandType">执行类型，默认为执行sql</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认120秒</param>
        /// <returns>查询结果的DataTable对象，含有表的主键信息</returns>
        DataTable QueryWithKeyInfo(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null);

        /// <summary>
        ///  批量插入数据，返回成功的行数
        ///  示例：
        ///   var table = MysqlContext.ListToDataTable(list);
        ///   table.TableName = "info_city";
        ///   context.BulkInsert(table);
        /// </summary>
        /// <param name="table">数据表对象</param>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        /// <param name="timeout">操作超时时间，单位秒，为null的时候默认600秒</param>
        /// <returns>成功的行数</returns>
        int BulkInsert(DataTable table, bool close = true, int? timeout = null);

        /// <summary>
        /// 将当前连接的操作指定为事务
        /// 注意该方法只是启动事务，需要结合commit和rollback方法一起使用
        /// </summary>
        /// <param name="isolationLevel">事务级别</param>
        void BeginTrans(IsolationLevel? isolationLevel);

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        void Commit(bool close = true);

        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <param name="close">true标识执行完成后关闭数据库连接</param>
        void Rollback(bool close = true);

        /// <summary>
        /// 是否是否开启
        /// true标识事务已开启
        /// </summary>
        /// <returns>true标识事务已开启</returns>
        bool IsTransOpen();
    }
}
